package com.kj.tms.common.utils;

import org.apache.commons.lang3.Validate;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * 获得spring上下文中的bean实例对象
 * @author zhaolj
 *
 */
@Component
public class SpringContextUtil implements ApplicationContextAware {

    // Spring应用上下文环境
    private static ApplicationContext applicationContext;

    /**
     * 获取对象
     * 
     * @param name              bean的id属性值或name属性值
     * @return Object           bean的实例对象
     * @throws BeansException
     */
    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);
    }

    /**
     * 获取类型为给定类类型的一个类实例对象
     * 如果bean不能被类型转换失败将抛出BeanNotOfRequiredTypeException）
     * 
     * @param name                 bean的id属性值或name属性值
     * @param requiredType         类类型
     * @return Object              类实例
     * @throws BeansException
     */
    public static Object getBean(String name, Class<?> requiredType) throws BeansException {
        return applicationContext.getBean(name, requiredType);
    }

    /**
     * BeanFactory是否包含指定bean
     * 
     * @param name        bean的id属性值或name属性值
     * @return boolean    是(包含)否(不包含)
     */
    public static boolean containsBean(String name) {
        return applicationContext.containsBean(name);
    }

    /**
     * applicationContext中获得bean的实例
     * @param requiredType     bean类对象
     * @return                 bean的实例，默认为单例
     */
    public static <T> T getBean(Class<T> requiredType) {
        assertContextInjected();
        return applicationContext.getBean(requiredType);
    }

    /**
     * 判断以给bean定义是否为singleton bean
     * 如果与给定名字相应的bean定义没有被找到，将会抛出NoSuchBeanDefinitionException
     * 
     * @param name        bean的id属性值或name属性值
     * @return boolean    是(单例)否(非单例)
     * @throws NoSuchBeanDefinitionException
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return applicationContext.isSingleton(name);
    }

    /**
     * 获得bean类类型
     * @param name        bean的id属性值或name属性值
     * @return Class      对象的类类型
     * @throws NoSuchBeanDefinitionException
     */
    @SuppressWarnings("rawtypes")
    public static Class getType(String name) throws NoSuchBeanDefinitionException {
        return applicationContext.getType(name);
    }

    /**
     * 从Spring上下文中获bean的所有别名
     * 
     * @param name             bean的id属性值或name属性值
     * @return                 bean别名数组
     * @throws NoSuchBeanDefinitionException
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return applicationContext.getAliases(name);
    }

    /*
     * ApplicationContext注入检查.
     */
    private static void assertContextInjected() {
        Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return SpringContextUtil.applicationContext;
    }
}
